package com.my.blog.interceptor;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.my.blog.annotation.AccessLimit;
import com.my.blog.myblog.entity.custom.RequestIp;
import com.my.blog.utils.UserIpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/***
 *
 * @Auther: MuYun
 * @Date: 2021/10/13 11:20
 * @Description：
 *
 */
@Component
public class AccessInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handle){
        if(handle instanceof HandlerMethod){

            HandlerMethod handlerMethod=(HandlerMethod)handle;
            AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
            //拦截的方法上没有@AccessLimit注解则直接放行，相当于实现了基于注解拦截
            if(ObjectUtil.isEmpty(accessLimit)){
                return true;
            }
            //System.out.println("有注解的进入拦截器");
            String ip = UserIpUtil.getIp(request);
            RequestIp reip = (RequestIp) request.getSession().getAttribute(ip);
            //session中没有ip，也就是第一次请求
            if(ObjectUtil.isEmpty(reip)){
                //System.out.println("第一次请求");
                RequestIp requestIp=new RequestIp();
                requestIp.setReCount(1);
                //返回当前的计算机时间，时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
                requestIp.setCreateTime(System.currentTimeMillis());
                //存入session，也就对应上面从session取的操作
                request.getSession().setAttribute(ip,requestIp);
            }else {
                //有ip了，那就不是第一次请求了
                //如果两次请求间隔时间（秒为单位）大于注解设置，则放行，再次记录下当前请求时间及ip
                //System.out.println("不是第一次请求");
                long createTime = reip.getCreateTime();
                //System.out.println((System.currentTimeMillis()-createTime)/1000);
                if((System.currentTimeMillis()-createTime)/1000>accessLimit.second()){
                    //System.out.println("时间满足");
                    RequestIp requestIp=new RequestIp();
                    requestIp.setReCount(1);
                    requestIp.setCreateTime(System.currentTimeMillis());
                    //存入session
                    request.getSession().setAttribute(ip,requestIp);
                }else {
                    //如果两次请求间隔时间（秒为单位）小于注解设置，也就是请求速度太快了
                    //如果在请求间隔小于设置的时间，请求次数又大于规定的最大请求次数,拦截请求。
                    if(reip.getReCount()>accessLimit.maxCount()){
                        //System.out.println("时间不满足，次数不满足");
                        try {
                            //这步注意要把500的错误码返回去，不然请求的状态码还是200，ajax回调函数跳不到error执行
                            response.sendError(500,"0.0");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        return false;
                    }else {
                        //System.out.println("时间不满足，次数满足");
                        //如果在请求间隔小于设置的时间，请求次数没有大于规定的最大请求次数,更新
                        reip.setReCount(reip.getReCount()+1);
                        reip.setCreateTime(System.currentTimeMillis());
                        request.getSession().setAttribute(ip,reip);
                    }
                }
            }
        }
        return true;
    }
}
